package d2_reflect;

import org.junit.Test;

import java.lang.reflect.Constructor;

public class Test2Constructor {

    @Test
    public void testGetConstructors() {
        //1、反射第一步: 必须先得到这个类的Class对象
        Class sc = Student.class;
        //2、获取类的全部构造器
        //2.1由于构造器不止一个,将构造器对象放到数组中返回给我们, 类型就是Constructor
        //2.2API-->学不完的-->只要一些出来,没有报错,就得记忆
        //2.3第一个无法获取被私有的构造器
        //Constructor[] constructors = sc.getConstructors();//只能拿public-->无法拿到私有的
        //2.4Declared : 声明的
        //2.5这个方法->就是只要你敢写,我就敢拿
        Constructor[] constructors = sc.getDeclaredConstructors();//只要类敢创建构造器,这个就可以拿,可以拿全部的构造器
        //3、遍历数组中的每一个构造器对象
        for (Constructor constructor : constructors) {
            System.out.println(constructor.getName() + "---->" +
                    +constructor.getParameterCount());

        }

    }


    @Test
    public void testGetConstructor() throws Exception {
        //1、反射第一步必须得到这个类的Class对象
        Class c = Student.class;
        //2、获取类的某个构造器: 无参构造器
        //害怕你没有写对参数,没有寻找到对应的构造器,直接编译时异常
        Constructor cons1 = c.getDeclaredConstructor();//无参构造器
        //3、获取有参数构造器
        Constructor cons2 = c.getDeclaredConstructor(int.class, String.class);
        //3.1 :String------>是一个类型符号
        //3.2 :String.class----->这个才是类型本身
        //3.3 :可以直接进行记忆即可

        //4、构造器的作用: 依然是初始化对象返回

        //4.2暴力反射
        //4.2.1暴力反射-->就是让虚拟机此时,不要去检查它的访问权限
        //4.2.2这个可以破坏封装性--->第一个小作用
        cons1.setAccessible(true);//不要检查构造器对象的访问权限
        Student student1 = (Student) cons1.newInstance();
        System.out.println(student1);

        //4.1在构造器带上泛型,就不需要强转(不建议)------->记忆即可
        //本质上还是调用构造器
        Student student = (Student) cons2.newInstance(18, "宁姚");//我们明确知道,是一个student类型
        //如果上面写了泛型,就不用强转

        System.out.println(student);
        /*
        //如果想拿单个构造器,就是必须声明参数类型,因为不止到你要拿的是什么构造器
        //参数是一个可变参数-------->是参数类型
        //这是做通用技术准备的,为底层源码准备的
        //后面就知道它有多牛逼了
        //为什么叫反射: 以前正面去寻找构造器,创建对象
        //现在是构造器找我们来创建对象-->已经是反过来了
         */
    }


}



